﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Rockfan.Framework;
using Rockfan.Framework.Graphics;
namespace Rockfan.Framework.Entities
{
    public sealed class Sustain : Sprite
    {
        public float TimeRemaining { get; private set; }

        /// <summary>
        /// Gets or Sets the Texture info used for this object during the normal state
        /// </summary>
        public TextureInfo NormalTexture { get; set; }

        /// <summary>
        /// Gets or Sets the Texture info used for a Dead Note
        /// </summary>
        public TextureInfo DeadTexture { get; set; }

        /// <summary>
        /// Gets or Sets the Texture info used for a Power Note
        /// </summary>
        public TextureInfo PowerTexture { get; set; }

        /// <summary>
        /// Gets or Sets the texture info used for this object during the overdrive state
        /// </summary>
        public TextureInfo OverdriveTexture { get; set; }

        /// <summary>
        /// Gets or Sets the Note type for this object
        /// </summary>
        public NoteType NoteType { get; set; }

        /// <summary>
        /// Gets a value indicating whether this note is currently dead
        /// </summary>
        public bool IsDead
        {
            get { return (NoteType & NoteType.Dead) == NoteType.Dead; }
        }

        /// <summary>
        /// Gets a value indicating whether this note is currently a power note
        /// </summary>
        public bool IsPower
        {
            get { return (NoteType & NoteType.Power) == NoteType.Power; }
        }

        /// <summary>
        /// Gets a value indicating whether this note is currently an overdrive note
        /// </summary>
        public bool IsOverdrive
        {
            get { return (NoteType & NoteType.Overdrive) == NoteType.Overdrive; }
        }

        #region Constructor

        /// <summary>
        /// Constructs a new instance of this object
        /// </summary>
        /// <param name="type">a PlayNoteType object defining the general characteristics of this object</param>
        public Sustain(NoteType type, float length, float delay)
            :base(null)
        {
            this.NoteType = type;
            this.TimeRemaining = length;
            this.TimeCreated = EngineServices.TotalGameTime;

            NormalTexture = new TextureInfo();
            DeadTexture = new TextureInfo();
            PowerTexture = new TextureInfo();
        }

        #endregion

        public void Initialize()
        {
            base.VerticesForDrawing[0].Color = Color.Transparent;
            base.VerticesForDrawing[1].Color = Color.Transparent;
            
            base.Update(0.0f);
        }

        public void SetOffsetAlpha(float alpha)
        {
            //var _Color = Color.White;

            //base.VerticesForDrawing[2].Color.PackedValue = (_Color.PackedValue & 0x00ffffff) | ((uint)(alpha * 255.0f) << 24);
            //base.VerticesForDrawing[3].Color.PackedValue = (_Color.PackedValue & 0x00ffffff) | ((uint)(alpha * 255.0f) << 24);
        }
        
        /// <summary>
        /// Swaps the position of the note over an amout of time in seconds
        /// </summary>
        /// <param name="delta">a float value indicating the amount of time in seconds it should take to swap the position of this note</param>
        public void Swap(float duration)
        {
            if (this.X == 0 || SwapDurationRemaining > 0)
                return;

            SwapDuration = duration;
            SwapDurationRemaining = duration;
            StartPosition = this.X;
            EndingPosition = this.X * -1;
        }

        public void UpdateState(float delta)
        {
            TimeRemaining -= delta;

            this.Update(delta);
        }

        protected override void Update(float delta)
        {
            // Check if the Note is dead
            if (IsDead)
            {
                if (DeadTexture != null)
                {
                    this.TopTextureCoordinate = DeadTexture.TopTextureCoordinate;
                    this.BottomTextureCoordinate = DeadTexture.BottomTextureCoordinate;
                    this.LeftTextureCoordinate = DeadTexture.LeftTextureCoordinate;
                    this.RightTextureCoordinate = DeadTexture.RightTextureCoordinate;
                    this.Texture = DeadTexture.Texture;
                }
            }

            // Else if In Overdrive
            else if (IsOverdrive)
            {
                if (OverdriveTexture != null)
                {
                    this.TopTextureCoordinate = OverdriveTexture.TopTextureCoordinate;
                    this.BottomTextureCoordinate = OverdriveTexture.BottomTextureCoordinate;
                    this.LeftTextureCoordinate = OverdriveTexture.LeftTextureCoordinate;
                    this.RightTextureCoordinate = OverdriveTexture.RightTextureCoordinate;
                    this.Texture = OverdriveTexture.Texture;
                }
            }

            // Else check if it's a power note
            else if (IsPower)
            {
                if (PowerTexture != null)
                {
                    this.TopTextureCoordinate = PowerTexture.TopTextureCoordinate;
                    this.BottomTextureCoordinate = PowerTexture.BottomTextureCoordinate;
                    this.LeftTextureCoordinate = PowerTexture.LeftTextureCoordinate;
                    this.RightTextureCoordinate = PowerTexture.RightTextureCoordinate;
                    this.Texture = PowerTexture.Texture;
                }
            }

            // otherwise set the texture info to the Normal Texture info
            else
            {
                if (NormalTexture != null)
                {
                    this.TopTextureCoordinate = NormalTexture.TopTextureCoordinate;
                    this.BottomTextureCoordinate = NormalTexture.BottomTextureCoordinate;
                    this.LeftTextureCoordinate = NormalTexture.LeftTextureCoordinate;
                    this.RightTextureCoordinate = NormalTexture.RightTextureCoordinate;
                    this.Texture = NormalTexture.Texture;
                }
            }

            if (SwapDurationRemaining > 0.0f)
            {
                this.X -= ((StartPosition - EndingPosition) / SwapDuration) * delta;

                SwapDurationRemaining -= delta;

                if (SwapDurationRemaining <= 0)
                    this.X = EndingPosition;
            }

            base.Update(delta);
        }
        
        private float SwapDuration;
        private float StartPosition;
        private float EndingPosition;
        private float SwapDurationRemaining;
    }
}
